/**
 * 
 */
package com.jjt.kiki.crawler;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.jjt.kiki.bean.Ip;

/**
 * @author jjtEatJava
 *
 */
public class HttpClientPool {
	private static final int CONNECTI_TIMEOUT = 3000;
	private static final int SO_TIMEOUT = 3000;
	private static final int SOCKET_TIMEOUT = 3000;
	private static final Logger logger = Logger.getLogger(HttpClientPool.class);
	private static class Single {
		private static HttpClientPool httpClientPool = new HttpClientPool();
	}

	private HttpClientPool() {

	}


	public static HttpClientPool getInstance() {
		return Single.httpClientPool;
	}

	public String create(String method, String url, Map<String, String> param, Map<String, String> header,long delay,boolean isProxy) {
		HttpRequestBase requestProxy = null;
		CloseableHttpResponse response = null;
		CloseableHttpClient client = null;
		Ip ip = null;
		while (true) {
			try {
				if(isProxy) {
					ip = ProxyOffer.getInstance().getIp();
					logger.info("使用ip："+ip.getIpHost()+":"+ip.getIpPort());
				}
				requestProxy = createRequest(method, url, param, header, isProxy,ip);
				client = HttpClients.createDefault();
				logger.info("HttpClient：开始进行请求");
				response = client.execute(requestProxy);
				logger.info("HttpClient：请求结束");
				if(response.getStatusLine().getStatusCode()!=200) {
					logger.info("状态码出错："+response.getStatusLine().getStatusCode());
					continue;
				}
				String json = EntityUtils.toString(response.getEntity());
				Integer errno = JSON.parseObject(json).getInteger("errno");
				if (errno != 0) {// 表示错误
					logger.info("出现错误，错误代码："+errno);
					if(errno==-55) {
						logger.info("HttpClientPool:代理被封.");
						if(!isProxy) {
							logger.info("本地请求，休息5分钟再尝试");
							Thread.sleep(60 * 5* 1000);
						}else {
							ProxyOffer.getInstance().expired(ip);
						}
						logger.info("HttpClientPool:再尝试");
						continue;
					}else {
						logger.info("出现其他错误，无法解决，返回空");
						response.close();
						client.close();
						return null;
					}
				}
				return json;
			} catch (Exception e) {// 代理错误
				e.printStackTrace();
				logger.info("HttpClientPool:代理出错...,再次尝试...");
				logger.info(requestProxy);
				if (isProxy)
					ProxyOffer.getInstance().expired(ip);
			}finally {
				if(client!=null) {
					if(response!=null) {
						try {
							EntityUtils.consume(response.getEntity());
							response.close();
						} catch (IOException e) {
							// 
							e.printStackTrace();
						}
					}
					try {
						client.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

	private HttpRequestBase createRequest(String method, String url, Map<String, String> param,
			Map<String, String> header, boolean isProxy,Ip ip) {
		if(header==null)
			header = new HashMap<String,String>();
		header.put("Connection", "close");
		// 构造参数
		if (param != null) {
			url = url + "?";
			for (Entry<String, String> entry : param.entrySet()) {
				url = url + entry.getKey() + "=" + entry.getValue() + "&";
			}
			url = url.substring(0, url.length() - 1);
		}
		if (method.equals("get")) {
			HttpGet get = new HttpGet(url);
			RequestConfig.Builder builder = RequestConfig.custom().setSocketTimeout(SOCKET_TIMEOUT).setConnectTimeout(CONNECTI_TIMEOUT).setConnectionRequestTimeout(SO_TIMEOUT);
			if (isProxy) {
				builder.setProxy(new HttpHost(ip.getIpHost(), ip.getIpPort()));
			}
			get.setConfig(builder.build());
			if (header != null) {
				for (Entry<String, String> entry : header.entrySet()) {
					get.setHeader(entry.getKey(), entry.getValue());
				}
			}
			logger.info(Thread.currentThread().getName() + ":" + get);
			return get;
		}
		return null;
	}

}
